using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Slaks.DocumentSerialization.Document;
using Slaks.DocumentSerialization.ParsedFiles;
using Slaks.DocumentSerialization.TermIdInfo;
using Slaks.Filters;
using Slaks.Graphs;
using Slaks.Graphs.Algorithms;
using Slaks.Graphs.Algorithms.ExperimentalDistances;
using Slaks.Graphs.Analysis;
using Slaks.Graphs.Category;
using Slaks.Graphs.GraphBuilder;
using Slaks.Graphs.ShenkerGraph.Algorithms;
using Slaks.Readers;
using TextParsing;
using Slaks.Graphs.Algorithms.DistanceAlgorithm;

namespace EndToEnd
{
    public class Experiment
    {
        public enum TaskType
        {
            Categorization,
            Clustering
        }
        private string _collectionName;
        private string _sourceFolder;
        private string _targetFolder;
        private Encoding _encoding;
        private IList _parsedFilesList;
        private TermIdInfoMap map;
        private CategoriesFile _categoriesFile;
        private string _categoryFileName;

        public IList ParsedFilesList
        {
            get { return _parsedFilesList; }
        }

        public BuilderType RepresentationType { get; set; }
        public string DistanceAlgorithm { get; set; }
        private GraphDistanceBase DistanceMeasure;
        public GraphList Graphs { get; set; }
        public TaskType Task { get; set; }
        public bool RemoveStopWords { get; set; }
        public string ResultsFile { get; set; }
        public int GraphSize{ get; set;}
        public int AdditionalParam { get; set;} 
        public bool SkipParsing{ get; set;}
        public int Iterations { get; set; }
        public void SetDocumentsCollection(string name,string sourceFolder, string targetFolder, string categoryFile, Encoding encoding)
        {
            _collectionName = name;
            _sourceFolder = sourceFolder;
            _targetFolder = targetFolder;
            _categoryFileName = categoryFile;
            _encoding = encoding;
        }
        public int EdgesWeight { get; set; }
        private void ReadCategories()
        {
            _categoriesFile = new CategoriesFile();
            _categoriesFile.FillCateogriesFromFile(_categoryFileName);
        }

        private void ParseDocuments()
        {
            try
            {
                if (!SkipParsing)
                {
                    var filesToParse = Directory.GetFiles(_sourceFolder, "*.htm?");
                    if (!Directory.Exists(_targetFolder))
                        Directory.CreateDirectory(_targetFolder);
                    var stopWordsFile = @"C:\Slava_Parser\Dlls\english_stopwords_schenker.txt";
                    var bufferReaderCore = new TermBufferReader(new EnglishTermFilter());
                    var structureConstruction = new StructureConstruction(bufferReaderCore, _targetFolder, _encoding,
                                                                          stopWordsFile, null);
                    structureConstruction.ProceedParsing(filesToParse);

                    map = structureConstruction.TermIdMap;
                    _parsedFilesList = ParsedFiles.ReadXml(structureConstruction.ParsedFileList);
                }
                else
                {
                    const string parsedFileListXml = @"parsed_file_list.xml";
                    string parsedFilelistName = Path.Combine(_targetFolder, parsedFileListXml);
                    if (File.Exists(parsedFilelistName))
                    {
                        _parsedFilesList = ParsedFiles.ReadXml(parsedFilelistName);
                    }
                    const string termIdMap = @"term_id_info.xml";
                    string mapFileName = Path.Combine(_targetFolder, termIdMap);
                    if (File.Exists(mapFileName))
                    {
                        map = TermIdInfo.ReadXml(mapFileName);
                    }
                }
                
            }
            catch (Exception)
            {
                _parsedFilesList = null;
                map = null;
            }
        }

        private void LoadGraphs()
        {
            if (Graphs == null)
            {
                Graphs = new GraphList();
            }


            foreach (string s in _parsedFilesList)
            {

                Document document = Xml2Document.ReadXml(s);

                IRepresentation representation = GraphBuilderFactory.Instance.GetInstance(RepresentationType.ToString("F"));
                try
                {
                    Graph newgraph;
                    if (representation != null)
                    {
                        newgraph = representation.Build(document, GraphSize, map);
                        newgraph.Category = _categoriesFile.DocumentToCategoryMap[Path.GetFileName(newgraph.Name)];
                    }

                    else throw new Exception("Invalid representation : " + RepresentationType);

                    Graphs.Add(newgraph);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);

                    //                    numberOfMissedGraphs++;
                }
            }
           
        }

        private void SetDistanceMeasure()
        {
            const string distanceAlgorithmValue1 = "MCS";
            const string distanceAlgorithmValue2 = "WGU";
            const string distanceAlgorithmValue3 = "SlaksMCS";
            const string distanceAlgorithmValue4 = "SlaksWGU";
            const string distanceAlgorithmValue5 = "CommonFeaturesModel";
            const string distanceAlgorithmValue6 = "MCSsubgraph";
            const string distanceAlgorithmValue7 = "WGUext";
            const string distanceAlgorithmValue8 = "MCSbalanced";
            const string distanceAlgorithmValue9 = "MCSmixed";
            const string distanceAlgorithmValue10 = "MCSseparate";
            const string distanceAlgorithmValue11 = "MCSlimited";
            const string distanceAlgorithmValue12 = "MCSadapted";
            const string distanceAlgorithmValue13 = "MCSedge-weight";
            const string distanceAlgorithmValue14 = "WGUbalanced";
            const string distanceAlgorithmValue15 = "WGUseparate";
            const string distanceAlgorithmValue16 = "WGUsubgraph";
            if (DistanceAlgorithm != null)
            {
                if (DistanceAlgorithm == distanceAlgorithmValue1)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new DistMCS4VertexEdgeCount ();
                    else
                        DistanceMeasure = new DistMCS4VertexEdgeFrequency ();

                    Console.WriteLine("MCS distance algorithm set with representation : " +
                                      RepresentationType.ToString());
                    //writer.WriteLine("MCS distance algorithm set with representation : " +
                    //                 RepresentationType.ToString());
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue2)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new DistWGU4VertexEdgeCount ();
                    else
                        DistanceMeasure = new DistWGU4VertexEdgeFrequency ();

                    Console.WriteLine("WGU distance algorithm set with representation : " +
                                      RepresentationType.ToString());
                    //writer.WriteLine("WGU distance algorithm set with representation : " +
                    //                 RepresentationType.ToString());
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue3)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new DistMCS4VertexEdgeCount();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with SlaksMCS distance measure");

                    Console.WriteLine("SlaksMCS distance algorithm set");
                    //writer.WriteLine("SlaksMCS distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue4)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new DistWGU4VertexEdgeCount();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with SlaksWGU distance measure");

                    Console.WriteLine("SlaksWGU distance algorithm set");
                    //writer.WriteLine("SlaksWGU distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue5)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new DistCommonFeaturesModel ();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with CommonFeaturesModel distance measure");

                    Console.WriteLine("CommonFeaturesModel distance algorithm set");
                    //writer.WriteLine("CommonFeaturesModel distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue6)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new MCSSubgraphVertexEdgeCount();
                    else if (RepresentationType == BuilderType.NormalizedFrequencyRepresentationSchenker ||
                             RepresentationType == BuilderType.NormalizedFrequencyRepresentationSlaks ||
                             RepresentationType == BuilderType.RawFrequencyRepresentationSchenker ||
                             RepresentationType == BuilderType.RawFrequencyRepresentationSlaks
                        )
                        DistanceMeasure =
                            new MCSSubgraphVertexEdgeFrequency();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with MCSsubgraph distance measure");

                    Console.WriteLine("MCSsubgraph distance algorithm set");
                    //writer.WriteLine("MCSsubgraph distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue10)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new MCSseparate();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with MCSseparate distance measure");

                    Console.WriteLine("MCSseparate distance algorithm set");
                    //writer.WriteLine("MCSseparate distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue8)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure = new MCSbalancedDistance();
                    else if (RepresentationType == BuilderType.StandardSimpleRepresentationSlaks)
                        DistanceMeasure = new MCSbalancedDistance();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with MCSbalanced distance measure");

                    Console.WriteLine("MCSbalanced distance algorithm set");
                    //writer.WriteLine("MCSbalanced distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue9)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure = new MCSmixed ();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with MCSmixed distance measure");

                    Console.WriteLine("MCSmixed distance algorithm set");
                    //writer.WriteLine("MCSmixed distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue11)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure = new MCSLimitedVertexEdgeCount ();
                    else if (RepresentationType == BuilderType.RawFrequencyRepresentationSlaks ||
                             RepresentationType == BuilderType.NormalizedFrequencyRepresentationSlaks)
                        DistanceMeasure = new MCSLimitedVertexEdgeFrequency ();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with MCSlimited distance measure");

                    Console.WriteLine("MCSlimited distance algorithm set");
                    //writer.WriteLine("MCSlimited distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue12)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure = new MCSAdaptedVertexEdgeCount ();
                    else if (RepresentationType == BuilderType.RawFrequencyRepresentationSlaks ||
                             RepresentationType == BuilderType.NormalizedFrequencyRepresentationSlaks)
                        DistanceMeasure = new MCSAdaptedVertexEdgeFrequency ();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with MCSadapted distance measure");

                    Console.WriteLine("MCSadapted distance algorithm set");
                    //writer.WriteLine("MCSadapted distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue13)
                {
                    MCSedge_weight.EdgeWeight = EdgesWeight;
                    Console.WriteLine("Edge weight paramete was set");
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure =
                            new MCSedge_weight ();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with MCSedge-weight distance measure");

                    Console.WriteLine("MCSedge-weight distance algorithm set");
                    //writer.WriteLine("MCSedge-weight distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue14)
                {
                    Console.WriteLine("WGUbalanced distance algorithm set");
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure = new WGUbalanced();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with WGUbalanced distance measure");

                    Console.WriteLine("WGUbalanced distance algorithm set");
                    //writer.WriteLine("WGUbalanced distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue15)
                {
                    Console.WriteLine("WGUseparate distance algorithm set");
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure = new MCSseparate();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with WGUseparate distance measure");

                    Console.WriteLine("WGUseparate distance algorithm set");
                    //writer.WriteLine("WGUseparate distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue16)
                {
                    Console.WriteLine("WGUsubgraph distance algorithm set");
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks)
                        DistanceMeasure = new MCSSubgraphVertexEdgeCount();
                    else
                        throw new Exception(RepresentationType +
                                            " is not compatible with WGUsubgraph distance measure");

                    Console.WriteLine("WGUsubgraph distance algorithm set");
                    //writer.WriteLine("WGUsubgraph distance algorithm set");
                }
                else if (DistanceAlgorithm == distanceAlgorithmValue7)
                {
                    if (RepresentationType == BuilderType.StandardRepresentationSchenker ||
                        RepresentationType == BuilderType.ExtractorBuilderNodesOnly ||
                        RepresentationType == BuilderType.StandardRepresentationSlaks ||
                        RepresentationType == BuilderType.SimpleRepresentationSchenker ||
                        RepresentationType == BuilderType.SimpleRepresentationSlaks ||
                        RepresentationType == BuilderType.NDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NDistanceRepresentationSlaks ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSchenker ||
                        RepresentationType == BuilderType.NSimpleDistanceRepresentationSlaks)
                        DistanceMeasure = new DistWGUVertexEdgeCountExtended ();
                    else

                        throw new Exception(RepresentationType + " is not compatible with WGUext distance measure");

                    Console.WriteLine("WGUext distance algorithm set");
                    //writer.WriteLine("WGUext distance algorithm set");
                }
                else
                {
                    //writer.WriteLine("Uknown distance algorithm : " + DistanceAlgorithm +
                    //                 " -> Must be [MSC,WGU,SlaksMCS,SkaksWGU]");
                    DistanceMeasure = null;
                    throw new Exception("Uknown distance algorithm : " + DistanceAlgorithm +
                                        " -> Must be [MSC,WGU,SlaksMCS,SkaksWGU]");
                }

            }
            else
            {
                //writer.WriteLine("No distance algorithm set");
                DistanceMeasure = null;
                throw new Exception("No distance algorithm set");
            }
        }
        public void RunExperiment()
        {
            ReadCategories();
            ParseDocuments();
            LoadGraphs();
            SetDistanceMeasure();
            switch (Task)
            {
                case TaskType.Categorization:
                    RunCategorization();
                    break;
                case TaskType.Clustering:
                    RunClustering();
                    break;
            }
        }

        private void RunClustering()
        {
            /*AdditionalParam = _categoriesFile.CategoryFrequencyMap.Count;
            for (int iteration = 0; iteration < Iterations; iteration++)
            {
                var clustering= new ShenkerGraphClustering(Graphs, AdditionalParam, DistanceMeasure);
                clustering.Apply();
                var dunnIndex = Slaks.Graphs.Analysis.ClusteringAnalysis.GetDunnIndex(clustering.GetGraphClusters(), DistanceMeasure);
                var randIndex = Slaks.Graphs.Analysis.ClusteringAnalysis.GetRandIndex(clustering.GetGraphClusters(), null);
                var mutualInfo = Slaks.Graphs.Analysis.ClusteringAnalysis.GetMutualInformation(clustering.GetGraphClusters(), null, CategoryReader.GetCategoryList(), clustering.CountGraphs());
                SaveResults(iteration, dunnIndex,randIndex,mutualInfo);

            }*/
        }

        private List<int>[] PartitionGraphs(int totalAmount)
        {
            Random rnd = new Random((int)DateTime.Now.Ticks);

            var result = new List<int>[Iterations];
            List<int> indices = new List<int>(totalAmount);
            for (int i = 0; i < totalAmount; i++)
            {
                indices.Add(i);
            }
            int partitionSize = (int)Math.Floor(totalAmount * 1.0 / Iterations);

            for (int i = 0; i < Iterations; i++)
            {
                result[i] = new List<int>();
                for (int j = 0; j < partitionSize; j++)
                {
                    int idx = rnd.Next(0, indices.Count);
                    result[i].Add(indices[idx]);
                    indices.RemoveAt(idx);
                }
            }
            if (indices.Count > 0)
            {
                for (int i = 0; i < Iterations && indices.Count > 0; i++)
                {
                    int idx = rnd.Next(0, indices.Count);
                    result[i].Add(indices[idx]);
                    indices.RemoveAt(idx);
                }
            }
            return result;
        }
        private static void GenerateTrainingAndTestSets(List<int>[] partitions, GraphList graphs, out GraphList trainingSet, out GraphList testSet, int iteration)
        {
            trainingSet = new GraphList();
            testSet = new GraphList();
            for (int i = 0; i < partitions.Length; i++)
            {
                if (i == iteration)
                {
                    foreach (int idx in partitions[i])
                    {
                        testSet.Add(graphs[idx]);
                    }
                }
                else
                {
                    foreach (int idx in partitions[i])
                    {
                        trainingSet.Add(graphs[idx]);
                    }

                }
            }
        }
        private void RunCategorization()
        {
            GraphList trainingSet;
            GraphList testSet;
            if (Partitions == null)
            {
                Partitions = PartitionGraphs(ParsedFilesList.Count);
            }
            for (int iteration = 0; iteration < Iterations; iteration++)
            {
                GenerateTrainingAndTestSets(Partitions, Graphs, out trainingSet, out testSet, iteration);
                var classifying = new ShenkerGraphClassifying(trainingSet, AdditionalParam, DistanceMeasure);
                var resultsSet = classifying.Apply(testSet, _categoriesFile.DocumentToCategoryMap);
                var accuracy = IRAnalysis.GetAccuracy(resultsSet, _categoriesFile);

                SaveResults(iteration, accuracy);
   
            }
        }

        public List<int>[] Partitions { get; set; }

        public void SaveResults(int iteration, params double[] measurements)
        {

            var outputFile = new StreamWriter(ResultsFile+Task+".txt", true);
            outputFile.Write(Task);
            outputFile.Write(',');
            outputFile.Write(AdditionalParam);
            outputFile.Write(',');
            outputFile.Write(_collectionName);
            outputFile.Write(',');
            outputFile.Write(iteration);
            outputFile.Write(',');
            outputFile.Write(RepresentationType);
            outputFile.Write(',');
            for (int i = 0; i < measurements.Length; i++)
            {
                outputFile.Write(measurements[i]);
                outputFile.Write(',');

            }
            outputFile.WriteLine();
            outputFile.Close();
        }
    }
}